﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;

using FarseerPhysics.Factories;
using FarseerPhysics.Dynamics.Joints;

using ZoeEngine.Framework;
using ZoeEngine.Services.Physics;

namespace ZoeEngine.Components.Physics
{
    public class PhysWheelJoint : EntityComponent
    {
        private WheelJoint _joint = null;

        private PhysBodyComponent _physBody = null;
        private PhysicsProvider _physicsProvider = null;

        private bool _motorEnabled = false;
        private float _motorSpeed = 0.0f;
        private float _motorTorque = 10.0f;
        private float _springFrequency = 4.0f;
        private float _springDamping = 0.7f;

        private PhysBodyComponent _attachment = null;
        private Vector2 _anchor = Vector2.Zero;

        public PhysWheelJoint(PhysBodyComponent attachment)
        {
            _attachment = attachment;
        }
        public override void Initialize()
        {
            base.Initialize();
        }
        public override void Start()
        {
            base.Start();

            // Retrieve local component references.
            _physBody = this.Owner.Find<PhysBodyComponent>();

            // Retrieve global service references. 
            _physicsProvider = Zoe.GetService<IPhysicsService>() as PhysicsProvider;
            if (_physicsProvider == null)
            {
                throw new ArgumentException("Could not locate appropriate service or provider is of incorrect type.");
            }

            // Create the joint and add it to the simulation.
            _joint = JointFactory.CreateWheelJoint(_physicsProvider.World, _physBody.Body, _attachment.Body, _anchor, new Vector2(1.0f, 0.0f));

            // Apply pre-set attributes.
            _joint.MotorSpeed = _motorSpeed;
            _joint.MotorEnabled = _motorEnabled;
            _joint.MaxMotorTorque = _motorTorque;
            _joint.SpringFrequencyHz = _springFrequency;
            _joint.SpringDampingRatio = _springDamping;
        }

        public Vector2 Anchor
        {
            get
            {
                return (_joint != null) ? Utility.ToPixels(_joint.LocalAnchorB) : Utility.ToPixels(_anchor);
            }
            set
            {
                _anchor = Utility.ToMeters(value);
                if (_joint != null)
                    _joint.LocalAnchorB = Utility.ToMeters(value);
            }
        }
        public bool MotorEnabled
        {
            get
            {
                return (_joint != null) ? _joint.MotorEnabled : _motorEnabled;
            }
            set
            {
                _motorEnabled = value;
                if (_joint != null)
                    _joint.MotorEnabled = value;
            }
        }
        public float MotorSpeed
        {
            get
            {
                return (_joint != null) ? _joint.MotorSpeed : _motorSpeed;
            }
            set
            {
                _motorSpeed = value;
                if (_joint != null)
                    _joint.MotorSpeed = value;
            }
        }
    }
}
